package cc.yugu.yhdw.webserver.biz.client;

import cc.yugu.yhdw.common.constant.CacheKey;
import cc.yugu.yhdw.common.constant.TsRespCode;
import cc.yugu.yhdw.common.domain.basic.Passport;
import cc.yugu.yhdw.common.domain.hdw.Cabinet;
import cc.yugu.yhdw.common.domain.hdw.CabinetBox;
import cc.yugu.yhdw.common.entity.RespBody;
import cc.yugu.yhdw.common.entity.json.ExtResult;
import cc.yugu.yhdw.common.protocol.msg05.*;
import cc.yugu.yhdw.common.utils.YhdwUtils;
import cc.yugu.yhdw.webserver.config.AppConfig;
import cc.yugu.yhdw.webserver.service.basic.SystemConfigService;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 客户端工具类
 *
 * @Date:Created in 2018/6/27 9:21
 * @Author:
 * @Modified By: zjn 2018/6/27 9:21
 */
public class ClientBizUtils {
    //一个静态方法，参数对应一个类(通过反射获取类参数)，也就是为ClientBizUtils类生成一个log日志对象，
    static Logger log = LogManager.getLogger(ClientBizUtils.class);
    /*创建具有初始值 0 的新 AtomicLong 原子类 对象,,主要是结合HashMap来用，作为HashMap的有序索引，
          最常用的方法是incrementAndGet()和decrementAndGet() ，用来自动增长序列。*/
    private static final AtomicLong sequence = new AtomicLong();
    static final long RESP_WAIT_TIME = 1000 * 5; //5秒
    protected static Map<Long, RespBody> respBodyPool = new ConcurrentHashMap<Long, RespBody>();
    /**
    * 策略更新
    *
    * @Param: [config, strategyId]
    * @Return: void
    * @Author By: zjn 2018/6/27  9:27
    */
    public static void noticeStrategyChanged(AppConfig config, int strategyId) {
        Msg051000002 message = new Msg051000002();
        message.setSerial(sequence.incrementAndGet());
        message.strategyId = strategyId;
        config.terminalServerClientManager.writeAndFlush(message);
    }

    /**
    * 终端温度更新
    *
    * @Param: [config, cabinet]
    * @Return: void
    * @Author By: zjn 2018/6/27  9:30
    */
    public static void cabinetChanged(AppConfig config, Cabinet cabinet) {
        Msg051000009 message = new Msg051000009();
        message.setSerial(sequence.incrementAndGet());
        message.cabinetId = cabinet.getId();
        message.fst = cabinet.getFst();
        message.fot = cabinet.getFot();
        message.pt = cabinet.getPt();
        message.rpt = cabinet.getRpt();
        config.terminalServerClientManager.writeAndFlush(message);
    }

    /**
     * 开箱
     *
     * @param config
     * @param terminalId
     * @param boxNum
     * @return
     * @throws InterruptedException
     */
    public static ExtResult noticeOpenBox(AppConfig config, String terminalId, String boxNum) throws InterruptedException {

        String key = (String) config.memCachedClient.get(CacheKey.key(CacheKey.K_ID_V_LOGIN_SERVER, terminalId));
        if (StringUtils.isEmpty(key)) {
            return ExtResult.failResult("终端不在线");
        }
        Msg051000003 message = new Msg051000003();

        message.cabinetId = terminalId;
        message.boxNum = boxNum;
        message.setSerial(sequence.incrementAndGet());
        Msg052000003 resp = null;
        try {
            RespBody<Msg052000003> respBody = new RespBody<Msg052000003>(RESP_WAIT_TIME);
            respBodyPool.put(message.getSerial(), respBody);
            if (config.terminalServerClientManager.writeAndFlush(key, message) == null) {
                return ExtResult.failResult("与业务服务器连接失败");
            }
            resp = respBody.getBody();
        } finally {
            respBodyPool.remove(message.getSerial());
        }

        if (resp == null) {
            return ExtResult.failResult("终端响应超时");
        } else if (resp.rtnCode == TsRespCode.CODE_0.getValue()) {
            return ExtResult.successResult("开箱成功");
        } else if (resp.rtnCode == TsRespCode.CODE_3.getValue()) {
            return ExtResult.successResult(TsRespCode.CODE_3.getName());
        } else if (resp.rtnCode == TsRespCode.CODE_4.getValue()) {
            return ExtResult.successResult(TsRespCode.CODE_4.getName());
        } else if (resp.rtnCode == TsRespCode.CODE_6.getValue()) {
            return ExtResult.failResult(resp.rtnMsg);
        } else if (resp.rtnCode == TsRespCode.CODE_1.getValue()) {
            return ExtResult.failResult(TsRespCode.CODE_1.getName());
        } else {
            throw new IllegalArgumentException();
        }
    }

    /**
     * 箱体更新通知
     *
     * @param config
     * @param cabinetId
     * @param boxs
     * @throws InterruptedException
     */
    public static void noticeBox(AppConfig config, String cabinetId, List<CabinetBox> boxs) {
        Msg051000010 message = new Msg051000010();
        message.cabinetId = cabinetId;
        for (CabinetBox cabinetBox : boxs) {
            Msg051000010.Box box = new Msg051000010.Box();
            box.boxNum = cabinetBox.getBoxNum();
            box.active = cabinetBox.getActiveFlag().byteValue();
            box.boxStatus = cabinetBox.getBoxStatus().byteValue();
            message.boxs.add(box);
        }
        message.setSerial(sequence.incrementAndGet());
        config.terminalServerClientManager.writeAndFlush(message);
    }

    /**
     * 设备配置变更通知
     *
     * @param config
     * @param cabinetIds
     */
    public static void noticeEquipment(AppConfig config, List<String> cabinetIds) {
        Msg051000013 message = new Msg051000013();
        for (String cabinetId : cabinetIds) {
            message.cabinetId = cabinetId;
            message.setSerial(sequence.incrementAndGet());
            config.terminalServerClientManager.writeAndFlush(message);
        }
    }

    /**
     * 上传终端日志
     *
     * @param config
     * @param cabinetId
     * @param type
     * @param date
     * @param url
     */
    public static ExtResult upload(AppConfig config, String cabinetId, int type, String date, String url) throws Exception {
        String key = (String) config.memCachedClient.get(CacheKey.key(CacheKey.K_ID_V_LOGIN_SERVER, cabinetId));
        if (StringUtils.isEmpty(key)) {
            return ExtResult.failResult("终端不在线");
        }
        Msg051000011 message = new Msg051000011();
        Msg052000011 resp = null;
        try {
            message.cabinetId = cabinetId;
            message.type = (byte) type;
            message.date = date;
            message.url = url;
            message.setSerial(sequence.incrementAndGet());

            RespBody<Msg052000011> respBody = new RespBody<Msg052000011>(RESP_WAIT_TIME);
            respBodyPool.put(message.getSerial(), respBody);
            if (config.terminalServerClientManager.writeAndFlush(key, message) == null) {
                return ExtResult.failResult("与业务服务器连接失败");
            }
            resp = respBody.getBody();
        } finally {
            respBodyPool.remove(message.getSerial());
        }

        if (resp == null) {
            return ExtResult.failResult("终端响应超时");
        } else if (resp.rtnCode == TsRespCode.CODE_3.getValue()) {
            return ExtResult.failResult(TsRespCode.CODE_3.getName());
        } else if (resp.rtnCode == TsRespCode.CODE_4.getValue()) {
            return ExtResult.failResult(TsRespCode.CODE_4.getName());
        } else if (resp.rtnCode == TsRespCode.CODE_1.getValue()) {
            return ExtResult.failResult(TsRespCode.CODE_1.getName());
        }
        Map map = (Map) YhdwUtils.decodeJson(resp.url, Map.class);
        Map data = (Map) map.get("data");
        return ExtResult.successResult((String) data.get("filePath"));
    }

    /**
     * 用户变更通知
     *
     * @param config
     * @param cabinetIds
     * @param createList
     * @param updateList
     * @param deleteList
     */
    public static void noticeCustomer(AppConfig config, List<String> cabinetIds, List<Passport> createList, List<Passport> updateList, List<Passport> deleteList) {
        /*
        新增（启用）
         */
        Msg051000012.Customer createCustomer = new Msg051000012.Customer();
        if (updateList.size() > 0) {
            for (Passport passport : createList) {
                createCustomer.id = passport.getId();
                createCustomer.mobile = passport.getMobile();
                createCustomer.password = passport.getPassword();
                createCustomer.balance = passport.getBalance();
                createCustomer.batteryId = passport.getBatteryId();
            }
        }
        /*
        更新（客户信息更改）
         */
        Msg051000012.Customer updateCustomer = new Msg051000012.Customer();
        if (updateList.size() > 0) {
            for (Passport passport : updateList) {
                updateCustomer.id = passport.getId();
                updateCustomer.mobile = passport.getMobile();
                updateCustomer.password = passport.getPassword();
                updateCustomer.balance = passport.getBalance();
                updateCustomer.batteryId = passport.getBatteryId();
            }
        }
         /*
        删除（禁用）
         */
        Msg051000012.Customer deleteCustomer = new Msg051000012.Customer();
        if (deleteList.size() > 0) {
            for (Passport passport : deleteList) {
                deleteCustomer.id = passport.getId();
                deleteCustomer.mobile = passport.getMobile();
                deleteCustomer.password = passport.getPassword();
                deleteCustomer.balance = passport.getBalance();
                deleteCustomer.batteryId = passport.getBatteryId();

            }
        }
        for (String cabinetId : cabinetIds) {
            Msg051000012 message = new Msg051000012();
            message.createList.add(createCustomer);
            message.updateList.add(updateCustomer);
            message.deleteList.add(deleteCustomer);
            message.cabinetId = cabinetId;
            message.setSerial(sequence.incrementAndGet());
            config.terminalServerClientManager.writeAndFlush(message);
        }
    }

    /**
     * 终端截屏
     *
     * @param config
     * @param terminalId
     * @return
     * @throws InterruptedException
     */
    public static ExtResult noticeTerminalScreenshot(AppConfig config, String terminalId) throws InterruptedException {
        String key = (String) config.memCachedClient.get(CacheKey.key(CacheKey.K_ID_V_LOGIN_SERVER, terminalId));
        if (StringUtils.isEmpty(key)) {
            return ExtResult.failResult("终端不在线");
        }

        Msg051000004 message = new Msg051000004();
        Msg052000004 resp = null;
        try {
            message.cabinetId = terminalId;
            message.setSerial(sequence.incrementAndGet());

            RespBody<Msg052000004> respBody = new RespBody<Msg052000004>(RESP_WAIT_TIME);
            respBodyPool.put(message.getSerial(), respBody);
            if (config.terminalServerClientManager.writeAndFlush(key, message) == null) {
                return ExtResult.failResult("与业务服务器连接失败");
            }
            resp = respBody.getBody();
        } finally {
            respBodyPool.remove(message.getSerial());
        }

        if (resp == null) {
            return ExtResult.failResult("终端响应超时");
        } else if (resp.rtnCode == TsRespCode.CODE_3.getValue()) {
            return ExtResult.failResult(TsRespCode.CODE_3.getName());
        } else if (resp.rtnCode == TsRespCode.CODE_4.getValue()) {
            return ExtResult.failResult(TsRespCode.CODE_4.getName());
        } else if (resp.rtnCode == TsRespCode.CODE_7.getValue()) {
            return ExtResult.failResult(TsRespCode.CODE_7.getName());
        }
        return ExtResult.successResult();
    }

    public static void noticeTerminalProperty(AppConfig config, String terminalId) {
//        Msg111000008 message = new Msg111000008();
//        message.setSerial(sequence.incrementAndGet());
//        message.terminalId = terminalId;
//        config.terminalServerClientManager.writeAndFlush(message);
    }

    public static void noticeTerminalChanged(AppConfig config, String terminalId) {
//        Msg111000010 message = new Msg111000010();
//        message.setSerial(sequence.incrementAndGet());
//        message.terminalId = terminalId;
//        config.terminalServerClientManager.writeAndFlush(message);
    }


}
